// Copyright 2007 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lichen.services;

import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import java.util.Map.Entry;

import lichen.entities.forum.Forum;
import lichen.entities.forum.ForumImpl;
import lichen.entities.user.User;
import lichen.hibernate.EntityService;
import lichen.hibernate.HibernateModule;
import lichen.internal.bindings.ListBindingFactory;
import lichen.internal.job.SchedulerFactoryProxy;
import lichen.internal.job.SchedulerJobModule;
import lichen.internal.services.ForumClassServiceImpl;
import lichen.internal.services.MenuServiceImpl;
import lichen.internal.services.PostServiceImpl;
import lichen.internal.services.UserServiceImpl;
import lichen.render.RenderModule;
import lichen.security.SecurityModule;
import lichen.typecoercer.TypeCoercerModule;
import lichen.validator.ValidatorModule;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.OrderedConfiguration;
import org.apache.tapestry.ioc.ServiceBinder;
import org.apache.tapestry.ioc.annotations.Inject;
import org.apache.tapestry.ioc.annotations.SubModule;
import org.apache.tapestry.services.ApplicationInitializer;
import org.apache.tapestry.services.ApplicationInitializerFilter;
import org.apache.tapestry.services.BindingFactory;
import org.apache.tapestry.services.BindingSource;
import org.apache.tapestry.services.Context;
import org.quartz.SchedulerFactory;

/**
 * 对tapestry的扩展
 * @author <a href="mailto:jun.tsai@gmail.com">Jun Tsai</a>
 * @version $Revision: 178 $
 * @since 0.0.1
 */
@SubModule({HibernateModule.class,ValidatorModule.class,SchedulerJobModule.class,RenderModule.class,TypeCoercerModule.class,SecurityModule.class})
public class LichenModule {

	/** 系统启动时候的jvm配置参数,此参数决定是否初始化数据 **/
	private static final String LICHEN_ENV_NAME="lichen.env";
	/** 系统处于产品环境 **/
	private static final String LICHEN_ENV_PRODUCT="product";

	/** lichen 的版本 **/
	public static final String LICHEN_VERSION_KEY_NAME = "lichen.version";
	

	/**
	 * 绑定使用的service.
	 * @param binder Service Binder
	 * @see ServiceBinder
	 */
	public static void bind(ServiceBinder binder) {
		binder.bind(ForumClassService.class, ForumClassServiceImpl.class);
		binder.bind(PostService.class,PostServiceImpl.class);
		binder.bind(UserService.class,UserServiceImpl.class);
		binder.bind(SchedulerFactory.class,SchedulerFactoryProxy.class);
		binder.bind(MenuService.class,MenuServiceImpl.class);
	}



	/**
	 * 初始化网站的数据
	 * @param configuration 配置
	 * @param treeService tree service.
	 */
	public void contributeApplicationInitializer(
			OrderedConfiguration<ApplicationInitializerFilter> configuration,
			@Inject
			final EntityService entityService, @Inject
			final ForumClassService treeService
			) {
		//当环境为产品环境的时候，则不进行初始化一些数据
		if(LICHEN_ENV_PRODUCT.equalsIgnoreCase(System.getProperty(LICHEN_ENV_NAME))){
			return;
		}
		ApplicationInitializerFilter clearCaches = new ApplicationInitializerFilter() {
			public void initializeApplication(Context context,
					ApplicationInitializer initializer) {
				Forum category = new ForumImpl();
				category.setName("Java 技术");
				treeService.saveTreeChildNode(category, null, null);
				
				
//				Transaction t = session.beginTransaction();
				Forum forum = new ForumImpl();
				forum.setName("J2SE");
				forum.setDescription("Java的基础知识");
				treeService.saveTreeChildNode(forum, category, null);
//				t.commit();
				
				entityService.refresh(category);
				User ud = new User();
		        ud.setEmail("asdf@asdf.net");
		        ud.setPassword(DigestUtils.md5Hex("asdf"));
		        ud.addRole("ROLE_USER");
		        ud.addRole("ROLE_ADMIN");
		        entityService.save(ud);
				initializer.initializeApplication(context);
			}
		};
		configuration.add("initialDataBase", clearCaches);
	}

	/**
	 * 修改默认页面 为index
	 * 
	 * @param configuration            配置.
	 */
	public void contributeApplicationDefaults(
			MappedConfiguration<String, String> configuration) {
		//默认的配置页面
		configuration.add("tapestry.start-page-name", "index");
		//默认的样式
		configuration.add("lichen.skin", "default");
		
		//acegi测试配置
        configuration.add("acegi.failure.url", "/user/login/failed");
        configuration.add("acegi.loginform.url","/user/login/");
        configuration.add("acegi.password.encoder", "org.acegisecurity.providers.encoding.Md5PasswordEncoder");
//        configuration.add("acegi.check.url", "index");
        
		//lichen 的版本
		Properties properties=new Properties();
		try {
			properties.load(LichenModule.class.getResourceAsStream("/version.properties"));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		Iterator<Entry<Object, Object>> it = properties.entrySet().iterator();
		while(it.hasNext()){
			Entry<Object, Object> entry = it.next();
			configuration.add(entry.getKey().toString(),entry.getValue().toString());
		}
	}


	/**
	 * 扩展binding source,实现一个list的绑定.
	 * @param configuration 配置
	 * @param bindingSource binding source
	 * @see ListBindingFactory
	 */
	public static void contributeBindingSource(
            MappedConfiguration<String, BindingFactory> configuration,
            BindingSource bindingSource)
    {
        configuration.add("list",new ListBindingFactory(bindingSource));
    }
    

    

}
